home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / Net / Socket.php < prev    next >
PHP Script  |  2004-10-01  |  13KB  |  457 lines

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Stig Bakken <ssb@php.net>                                   |
  17. // |          Chuck Hagenbuch <chuck@horde.org>                           |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: Socket.php,v 1.9 2004/04/26 23:02:41 chagenbu Exp $
  21. //
  22.  
  23. require_once 'PEAR.php';
  24.  
  25. /**
  26.  * Generalized Socket class. More docs to be written.
  27.  *
  28.  * @version 1.0
  29.  * @author Stig Bakken <ssb@php.net>
  30.  * @author Chuck Hagenbuch <chuck@horde.org>
  31.  */
  32. class Net_Socket extends PEAR {
  33.     // {{{ properties
  34.  
  35.     /** Socket file pointer. */
  36.     var $fp = null;
  37.  
  38.     /** Whether the socket is blocking. */
  39.     var $blocking = true;
  40.  
  41.     /** Whether the socket is persistent. */
  42.     var $persistent = false;
  43.  
  44.     /** The IP address to connect to. */
  45.     var $addr = '';
  46.  
  47.     /** The port number to connect to. */
  48.     var $port = 0;
  49.  
  50.     /** Number of seconds to wait on socket connections before
  51.         assuming there's no more data. */
  52.     var $timeout = false;
  53.  
  54.     /** Number of bytes to read at a time in readLine() and
  55.         readAll(). */
  56.     var $lineLength = 2048;
  57.     // }}}
  58.  
  59.     // {{{ constructor
  60.     /**
  61.      * Constructs a new Net_Socket object.
  62.      *
  63.      * @access public
  64.      */
  65.     function Net_Socket()
  66.     {
  67.         $this->PEAR();
  68.     }
  69.     // }}}
  70.  
  71.     // {{{ connect()
  72.     /**
  73.      * Connect to the specified port. If called when the socket is
  74.      * already connected, it disconnects and connects again.
  75.      *
  76.      * @param $addr string IP address or host name
  77.      * @param $port int TCP port number
  78.      * @param $persistent bool (optional) whether the connection is
  79.      *        persistent (kept open between requests by the web server)
  80.      * @param $timeout int (optional) how long to wait for data
  81.      * @param $options array see options for stream_context_create
  82.      * @access public
  83.      * @return mixed true on success or error object
  84.      */
  85.     function connect($addr, $port, $persistent = null, $timeout = null, $options = null)
  86.     {
  87.         if (is_resource($this->fp)) {
  88.             @fclose($this->fp);
  89.             $this->fp = null;
  90.         }
  91.  
  92.         if (strspn($addr, '.0123456789') == strlen($addr)) {
  93.             $this->addr = $addr;
  94.         } else {
  95.             $this->addr = gethostbyname($addr);
  96.         }
  97.         $this->port = $port % 65536;
  98.         if ($persistent !== null) {
  99.             $this->persistent = $persistent;
  100.         }
  101.         if ($timeout !== null) {
  102.             $this->timeout = $timeout;
  103.         }
  104.         $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
  105.         $errno = 0;
  106.         $errstr = '';
  107.         if ($options && function_exists('stream_context_create')) {
  108.             if ($this->timeout) {
  109.                 $timeout = $this->timeout;
  110.             } else {
  111.                 $timeout = 0;
  112.             }
  113.             $context = stream_context_create($options);
  114.             $fp = $openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context);
  115.         } else {
  116.             if ($this->timeout) {
  117.                 $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
  118.             } else {
  119.                 $fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
  120.             }
  121.         }
  122.  
  123.         if (!$fp) {
  124.             return $this->raiseError($errstr, $errno);
  125.         }
  126.  
  127.         $this->fp = $fp;
  128.  
  129.         return $this->setBlocking($this->blocking);
  130.     }
  131.     // }}}
  132.  
  133.     // {{{ disconnect()
  134.     /**
  135.      * Disconnects from the peer, closes the socket.
  136.      *
  137.      * @access public
  138.      * @return mixed true on success or an error object otherwise
  139.      */
  140.     function disconnect()
  141.     {
  142.         if (is_resource($this->fp)) {
  143.             fclose($this->fp);
  144.             $this->fp = null;
  145.             return true;
  146.         }
  147.         return $this->raiseError("not connected");
  148.     }
  149.     // }}}
  150.  
  151.     // {{{ isBlocking()
  152.     /**
  153.      * Find out if the socket is in blocking mode.
  154.      *
  155.      * @access public
  156.      * @return bool the current blocking mode.
  157.      */
  158.     function isBlocking()
  159.     {
  160.         return $this->blocking;
  161.     }
  162.     // }}}
  163.  
  164.     // {{{ setBlocking()
  165.     /**
  166.      * Sets whether the socket connection should be blocking or
  167.      * not. A read call to a non-blocking socket will return immediately
  168.      * if there is no data available, whereas it will block until there
  169.      * is data for blocking sockets.
  170.      *
  171.      * @param $mode bool true for blocking sockets, false for nonblocking
  172.      * @access public
  173.      * @return mixed true on success or an error object otherwise
  174.      */
  175.     function setBlocking($mode)
  176.     {
  177.         if (is_resource($this->fp)) {
  178.             $this->blocking = $mode;
  179.             socket_set_blocking($this->fp, $this->blocking);
  180.             return true;
  181.         }
  182.         return $this->raiseError("not connected");
  183.     }
  184.     // }}}
  185.  
  186.     // {{{ setTimeout()
  187.     /**
  188.      * Sets the timeout value on socket descriptor,
  189.      * expressed in the sum of seconds and microseconds
  190.      *
  191.      * @param $seconds int seconds
  192.      * @param $microseconds int microseconds
  193.      * @access public
  194.      * @return mixed true on success or an error object otherwise
  195.      */
  196.     function setTimeout($seconds, $microseconds)
  197.     {
  198.         if (is_resource($this->fp)) {
  199.             socket_set_timeout($this->fp, $seconds, $microseconds);
  200.             return true;
  201.         }
  202.         return $this->raiseError("not connected");
  203.     }
  204.     // }}}
  205.  
  206.     // {{{ getStatus()
  207.     /**
  208.      * Returns information about an existing socket resource.
  209.      * Currently returns four entries in the result array:
  210.      *
  211.      * <p>
  212.      * timed_out (bool) - The socket timed out waiting for data<br>
  213.      * blocked (bool) - The socket was blocked<br>
  214.      * eof (bool) - Indicates EOF event<br>
  215.      * unread_bytes (int) - Number of bytes left in the socket buffer<br>
  216.      * </p>
  217.      *
  218.      * @access public
  219.      * @return mixed Array containing information about existing socket resource or an error object otherwise
  220.      */
  221.     function getStatus()
  222.     {
  223.         if (is_resource($this->fp)) {
  224.             return socket_get_status($this->fp);
  225.         }
  226.         return $this->raiseError("not connected");
  227.     }
  228.     // }}}
  229.  
  230.     // {{{ gets()
  231.     /**
  232.      * Get a specified line of data
  233.      *
  234.      * @access public
  235.      * @return $size bytes of data from the socket, or a PEAR_Error if
  236.      *         not connected.
  237.      */
  238.     function gets($size)
  239.     {
  240.         if (is_resource($this->fp)) {
  241.             return fgets($this->fp, $size);
  242.         }
  243.         return $this->raiseError("not connected");
  244.     }
  245.     // }}}
  246.  
  247.     // {{{ read()
  248.     /**
  249.      * Read a specified amount of data. This is guaranteed to return,
  250.      * and has the added benefit of getting everything in one fread()
  251.      * chunk; if you know the size of the data you're getting
  252.      * beforehand, this is definitely the way to go.
  253.      *
  254.      * @param $size The number of bytes to read from the socket.
  255.      * @access public
  256.      * @return $size bytes of data from the socket, or a PEAR_Error if
  257.      *         not connected.
  258.      */
  259.     function read($size)
  260.     {
  261.         if (is_resource($this->fp)) {
  262.             return fread($this->fp, $size);
  263.         }
  264.         return $this->raiseError("not connected");
  265.     }
  266.     // }}}
  267.  
  268.     // {{{ write()
  269.     /**
  270.      * Write a specified amount of data.
  271.      *
  272.      * @access public
  273.      * @return mixed true on success or an error object otherwise
  274.      */
  275.     function write($data)
  276.     {
  277.         if (is_resource($this->fp)) {
  278.             return fwrite($this->fp, $data);
  279.         }
  280.         return $this->raiseError("not connected");
  281.     }
  282.     // }}}
  283.  
  284.     // {{{ writeLine()
  285.     /**
  286.      * Write a line of data to the socket, followed by a trailing "\r\n".
  287.      *
  288.      * @access public
  289.      * @return mixed fputs result, or an error
  290.      */
  291.     function writeLine ($data)
  292.     {
  293.         if (is_resource($this->fp)) {
  294.             return $this->write($data . "\r\n");
  295.         }
  296.         return $this->raiseError("not connected");
  297.     }
  298.     // }}}
  299.  
  300.     // {{{ eof()
  301.     /**
  302.      * Tests for end-of-file on a socket descriptor
  303.      *
  304.      * @access public
  305.      * @return bool
  306.      */
  307.     function eof()
  308.     {
  309.         return (is_resource($this->fp) && feof($this->fp));
  310.     }
  311.     // }}}
  312.  
  313.     // {{{ readByte()
  314.     /**
  315.      * Reads a byte of data
  316.      *
  317.      * @access public
  318.      * @return 1 byte of data from the socket, or a PEAR_Error if
  319.      *         not connected.
  320.      */
  321.     function readByte()
  322.     {
  323.         if (is_resource($this->fp)) {
  324.             return ord($this->read(1));
  325.         }
  326.         return $this->raiseError("not connected");
  327.     }
  328.     // }}}
  329.  
  330.     // {{{ readWord()
  331.     /**
  332.      * Reads a word of data
  333.      *
  334.      * @access public
  335.      * @return 1 word of data from the socket, or a PEAR_Error if
  336.      *         not connected.
  337.      */
  338.     function readWord()
  339.     {
  340.         if (is_resource($this->fp)) {
  341.             $buf = $this->read(2);
  342.             return (ord($buf[0]) + (ord($buf[1]) << 8));
  343.         }
  344.         return $this->raiseError("not connected");
  345.     }
  346.     // }}}
  347.  
  348.     // {{{ readInt()
  349.     /**
  350.      * Reads an int of data
  351.      *
  352.      * @access public
  353.      * @return 1 int of data from the socket, or a PEAR_Error if
  354.      *         not connected.
  355.      */
  356.     function readInt()
  357.     {
  358.         if (is_resource($this->fp)) {
  359.             $buf = $this->read(4);
  360.             return (ord($buf[0]) + (ord($buf[1]) << 8) +
  361.                     (ord($buf[2]) << 16) + (ord($buf[3]) << 24));
  362.         }
  363.         return $this->raiseError("not connected");
  364.     }
  365.     // }}}
  366.  
  367.     // {{{ readString()
  368.     /**
  369.      * Reads a zeroterminated string of data
  370.      *
  371.      * @access public
  372.      * @return string, or a PEAR_Error if
  373.      *         not connected.
  374.      */
  375.     function readString()
  376.     {
  377.         if (is_resource($this->fp)) {
  378.             $string = '';
  379.             while (($char = $this->read(1)) != "\x00")  {
  380.                 $string .= $char;
  381.             }
  382.             return $string;
  383.         }
  384.         return $this->raiseError("not connected");
  385.     }
  386.     // }}}
  387.  
  388.     // {{{ readIPAddress()
  389.     /**
  390.      * Reads an IP Address and returns it in a dot formated string
  391.      *
  392.      * @access public
  393.      * @return Dot formated string, or a PEAR_Error if
  394.      *         not connected.
  395.      */
  396.     function readIPAddress()
  397.     {
  398.         if (is_resource($this->fp)) {
  399.             $buf = $this->read(4);
  400.             return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]),
  401.                            ord($buf[2]), ord($buf[3]));
  402.         }
  403.         return $this->raiseError("not connected");
  404.     }
  405.     // }}}
  406.  
  407.     // {{{ readLine()
  408.     /**
  409.      * Read until either the end of the socket or a newline, whichever
  410.      * comes first. Strips the trailing newline from the returned data.
  411.      *
  412.      * @access public
  413.      * @return All available data up to a newline, without that
  414.      *         newline, or until the end of the socket, or a PEAR_Error if
  415.      *         not connected.
  416.      */
  417.     function readLine()
  418.     {
  419.         if (is_resource($this->fp)) {
  420.             $line = '';
  421.             $timeout = time() + $this->timeout;
  422.             while (!$this->eof() && (!$this->timeout || time() < $timeout)) {
  423.                 $line .= $this->gets($this->lineLength);
  424.                 if (substr($line, -2) == "\r\n" ||
  425.                     substr($line, -1) == "\n") {
  426.                     return rtrim($line, "\r\n");
  427.                 }
  428.             }
  429.             return $line;
  430.         }
  431.         return $this->raiseError("not connected");
  432.     }
  433.     // }}}
  434.  
  435.     // {{{ readAll()
  436.     /**
  437.      * Read until the socket closes. THIS FUNCTION WILL NOT EXIT if the
  438.      * socket is in blocking mode until the socket closes.
  439.      *
  440.      * @access public
  441.      * @return All data until the socket closes, or a PEAR_Error if
  442.      *         not connected.
  443.      */
  444.     function readAll()
  445.     {
  446.         if (is_resource($this->fp)) {
  447.             $data = '';
  448.             while (!$this->eof())
  449.                 $data .= $this->read($this->lineLength);
  450.             return $data;
  451.         }
  452.         return $this->raiseError("not connected");
  453.     }
  454.     // }}}
  455.  
  456. }
  457.